
`define TX_IDLE             2'b00
`define TX_READING_DATA1    2'b01
`define TX_READING_DATA2    2'b10
`define TX_SENDING          2'b11

module riscv_uart_top(
    CLK_50M,
    RST_N,
    UART_RX,
    UART_TX,
    BEEP,
    core_clk,
    fifo_data_cs,            //高有效
    fifo_status_cs,            //高有效
    fifo_we,            //高有效
    fifo_wr_data,
    fifo_rd_data,
    fifo_status
);

input  CLK_50M;				
input  RST_N;				
input  UART_RX;				
output UART_TX;					
output BEEP;

input  core_clk;

input  fifo_data_cs;
input  fifo_status_cs;
input  fifo_we;
input  [7:0] fifo_wr_data;
output [7:0] fifo_rd_data;
output [3:0] fifo_status;

wire 		tx_bps_start;			
wire 		tx_bps_flag;		
reg  [7:0] 	tx_data;			

wire [7:0] tx_di; 
wire [7:0] tx_do; 
reg tx_re;
reg tx_start_flag;
wire tx_we, tx_empty_flag, tx_full_flag, has_data_to_send, is_sending;
reg [1:0] tx_state;

wire        rx_bps_start;			
wire        rx_bps_flag;		
wire [7:0]  rx_data;			
wire [7:0]  rx_di; 
wire [7:0]  rx_do; 
wire rx_we, rx_re, rx_empty_flag, rx_full_flag;
reg [1:0] rx_bps_edge;


assign has_data_to_send = ~tx_empty_flag;
assign is_sending = tx_bps_start;

assign tx_we = (fifo_data_cs==1 && fifo_we==1) ? 1 : 0;
assign tx_di = fifo_wr_data;
assign fifo_status = {rx_empty_flag, rx_full_flag, tx_empty_flag, tx_full_flag};

always @(posedge core_clk or negedge RST_N) begin
    if (~RST_N) begin
        tx_re <= 0;
        tx_start_flag <= 1;           //低有效
        tx_state <= `TX_IDLE;
    end
    else begin
        case (tx_state)
            `TX_IDLE: begin
                if (has_data_to_send && ~is_sending) begin
                    tx_state <= `TX_READING_DATA1;
                    tx_re <= 1'b1;
                end
            end
            `TX_READING_DATA1: begin
                tx_re <= 1'b0;
                tx_state <= `TX_READING_DATA2;
            end
            `TX_READING_DATA2: begin
                tx_state <= `TX_SENDING;
                tx_start_flag <= 1'b0;  //0有效
            end
            `TX_SENDING: begin
                if (tx_start_flag == 1'b0)
                    tx_start_flag <= 1'b1;  //0有效
                if (~is_sending)
                    tx_state <= `TX_IDLE;
            end
        endcase
    end
end

always @(negedge core_clk) begin
    if (tx_state == `TX_READING_DATA2) begin
        tx_data <= tx_do;
    end
end

uart_tx_fifo tx_fifo(
	.rst(RST_N),
	.di(tx_di), .clk(core_clk), .we(tx_we),
	.do(tx_do), .re(tx_re),
	.empty_flag(tx_empty_flag),
	.full_flag(tx_full_flag) 
);

always @(posedge core_clk or negedge RST_N) begin
    if (RST_N==0)
        rx_bps_edge <= 2'b00;
    else
        rx_bps_edge <= {rx_bps_edge[0], rx_bps_start};
end

assign rx_re = (fifo_data_cs==1 && fifo_we==0) ? 1 : 0;
assign fifo_rd_data = rx_do;
assign rx_di = rx_data;
assign rx_we = (rx_full_flag==0 && rx_bps_edge==2'b10) ? 1 : 0;

uart_rx_fifo rx_fifo(
	.rst(RST_N),
	.di(rx_di), .clk(core_clk), .we(rx_we),
	.do(rx_do), .re(rx_re),
	.empty_flag(rx_empty_flag),
	.full_flag(rx_full_flag) 
);

Uart_Bps_Module		Uart_Rx_Bps_Init
(	
	.CLK_50M			(CLK_50M		),	
	.RST_N				(RST_N			),	
	.bps_start			(rx_bps_start	),	    //Input
	.bps_flag			(rx_bps_flag	)	    //Output
);

Uart_Rx_Module			Uart_Rx_Init
(		
	.CLK_50M			(CLK_50M		),	
	.RST_N				(RST_N			),	
	.UART_RX			(UART_RX		),
	.rx_bps_start		(rx_bps_start	),	    //Output
	.rx_bps_flag		(rx_bps_flag	),	    //Input
	.out_rx_data		(rx_data	)	        //Output
);

Uart_Bps_Module		Uart_Tx_Bps_Init
(	
	.CLK_50M			(CLK_50M		),	
	.RST_N				(RST_N			),	
	.bps_start			(tx_bps_start	),	    // input
	.bps_flag			(tx_bps_flag	)	    // output
);

Uart_Tx_Module			Uart_Tx_Init
(		
	.CLK_50M			(CLK_50M		),
	.RST_N				(RST_N			),
	.UART_TX			(UART_TX		),	
	.tx_bps_start		(tx_bps_start	),	    // output 
	.tx_bps_flag		(tx_bps_flag	),	    // input: 发送完成变为0
	.tx_start_flag		(tx_start_flag  ),	    // input: 开始发送设为1
	.in_rx_data			(tx_data	    )	    // output
);

Beep_Module				Beep_Init
(
	.CLK_50M			(CLK_50M		),
	.RST_N				(RST_N			),	
	.BEEP				(BEEP			),	
	.KEY				(rx_data	    )	
);

endmodule

